﻿using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Windows;

namespace sunsetmp
{
    class CheckUpdate
    {
        string[] pathFiles = null;
        string[] sourceFiles = null;
        string destPath;
        string sourceUrl;
        bool notUpdate = false;

        public CheckUpdate(string path, string source)
        {
            if (path == null || source == null)
                return;
            if (path == "" || source == "")
                return;
            pathFiles = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
            destPath = path;
            sourceUrl = source;
            GetFilesList(source);
        }

        private void GetFilesList(string source)
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += bw_DoWork;
            bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            bw.RunWorkerAsync(source + "list.txt");
        }

        private void StartCheckUpdate()
        {
            if (pathFiles == null || pathFiles.Length == 0)
                StartAutoInstaller();
            else
                for (int i = 0; i < sourceFiles.Length; i++)
                {
                    if (notUpdate)
                        return;
                    string destFile = FindFile(pathFiles, sourceFiles[i], destPath);
                    if (destFile != null)
                    {
                        string[] split = sourceFiles[i].Split('~');
                        if (split[1] == "PLS.accdb" || split[1] == "VKL.accdb" || split[1] == "updater.exe")
                            continue;
                        if (EqualsCheckSum(sourceFiles[i], destFile) == false)
                            StartAutoInstaller();
                    }
                    else
                        StartAutoInstaller();
                }
        }

        private bool EqualsCheckSum(string sourceString, string destFilePath)
        {
            string[] split = sourceString.Split('~');
            string origCheckSum = CreateCheckSum(destFilePath);
            string newCheckSum = split[0];
            return origCheckSum == newCheckSum;
        }

        private void StartAutoInstaller()
        {
            notUpdate = true;
            if (MessageBox.Show(@"Появились обновления.
Обновить программу?", "Обновить?", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes) == MessageBoxResult.Yes)
            {
                string updaterFile = FindFile(pathFiles, "updater.exe", destPath);
                string sourceString = "";
                foreach (string s in sourceFiles)
                    if (s.IndexOf("updater.exe") != -1)
                    {
                        sourceString = s;
                        break;
                    }
                if (updaterFile == null)
                    StartDownloadUpdater(destPath + "updater.exe");
                else
                {
                    if (EqualsCheckSum(sourceString, updaterFile) == false)
                        StartDownloadUpdater(updaterFile);
                    else
                    {
                        Process.Start(updaterFile);
                        Application.Current.Shutdown();
                    }
                }
            }
                
        }

        private void StartDownloadUpdater(string updaterFile)
        {
            BackgroundWorker downW = new BackgroundWorker();
            downW.DoWork += downW_DoWork;
            downW.RunWorkerCompleted += downW_RunWorkerCompleted;
            downW.RunWorkerAsync(updaterFile + "~" + sourceUrl + "updater.exe");
        }

        void downW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
                MessageBox.Show(e.Error.Message);
            else
            {
                string updaterFile = destPath + "updater.exe";
                Process.Start(updaterFile);
                Application.Current.Shutdown();
            }
        }

        void downW_DoWork(object sender, DoWorkEventArgs e)
        {
            string path = e.Argument.ToString().Split('~')[0];
            string url = e.Argument.ToString().Split('~')[1];
            DownloadFile(url, path);
        }

        private string FindFile(string[] files, string file, string path)
        {
            if (file.IndexOf('~') != -1)
                file = file.Split('~')[1];
            foreach (string s in files)
                if (s.Replace(path, "") == file)
                    return s;
            return null;
        }

        private string CreateCheckSum(string filename)
        {
            using (var md5 = MD5.Create())
            using (var stream = System.IO.File.OpenRead(filename))
                return ToHex(md5.ComputeHash(stream), true);
        }

        public static string ToHex(byte[] bytes, bool upperCase)
        {
            StringBuilder result = new StringBuilder(bytes.Length * 2);
            for (int i = 0; i < bytes.Length; i++)
                result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));
            return result.ToString();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
                MessageBox.Show(e.Error.Message);
            else
            {
                string str = e.Result.ToString();
                str = str.Remove(str.Length - 1);
                sourceFiles = str.Replace("\r", "").Split('\n');
                StartCheckUpdate();
            }
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = DownloadFile(e.Argument.ToString());
        }

        private object DownloadFile(string url)
        {
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
            request.Method = WebRequestMethods.Ftp.DownloadFile;
            using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
            {
                Stream responseStream = response.GetResponseStream();
                using (StreamReader reader = new StreamReader(responseStream))
                    return reader.ReadToEnd();
            }
        }

        private void DownloadFile(string url, string dest)
        {
            string path = System.IO.Path.GetDirectoryName(dest);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
            request.KeepAlive = true;
            request.UsePassive = true;
            request.UseBinary = true;
            request.Method = WebRequestMethods.Ftp.DownloadFile;
            using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
            {
                Stream responseStream = response.GetResponseStream();
                using (var output = System.IO.File.OpenWrite(dest))
                    responseStream.CopyTo(output);
            }
        }
    }
}
